(define-module (list-utils)
  #:export (list-prefix?
            list-suffix?
            multirember*-with-equal-proc
            multirember-with-equal-proc
            multirember-equal
            multirember*-equal))


(define list-prefix?
  (λ (lst lst-prefix)
    (cond
     [(null? lst-prefix) #t]
     [(null? lst) #f]
     [else
      (cond
       [(equal? (car lst) (car lst-prefix))
        (list-prefix? (cdr lst) (cdr lst-prefix))]
       [else #f])])))


(define list-suffix?
  (λ (lst maybe-suffix)
    (cond
     [(null? maybe-suffix) #t]
     [(null? lst) #f]
     [else
      (cond
       [(equal? (car lst) (car maybe-suffix))
        (equal? lst maybe-suffix)]
       [else
        (list-suffix? (cdr lst) maybe-suffix)])])))


(define multirember*-with-equal-proc
  (λ (equal-proc)
    (λ (lst unwanted)
      (let loop ([remaining-list lst])
        (cond
         [(null? remaining-list)
          '()]
         ;; case for finding the unwanted element in the list
         [(equal-proc (car remaining-list) unwanted)
          (loop (cdr remaining-list))]
         ;; case for handling nested lists
         [(pair? (car remaining-list))
          (cons (loop (car remaining-list))
                (loop (cdr remaining-list)))]
         [else
          (cons (car remaining-list)
                (loop (cdr remaining-list)))])))))


(define multirember-with-equal-proc
  (λ (equal-proc)
    (λ (lst unwanted)
      (let loop ([remaining-list lst])
        (cond
         [(null? remaining-list)
          '()]
         [(equal-proc (car remaining-list) unwanted)
          (loop (cdr remaining-list))]
         [else
          (cons (car remaining-list)
                (loop (cdr remaining-list)))])))))


(define multirember-equal
  (multirember-with-equal-proc equal?))


(define multirember*-equal
  (multirember*-with-equal-proc equal?))
